package com.hs.android.fortress.ingame;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.hs.android.fortress.GameApplication;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.UiSettings;
import com.google.android.gms.maps.GoogleMap.CancelableCallback;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.Circle;
import com.google.android.gms.maps.model.CircleOptions;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;
import com.hs.android.fortress.R;
import com.hs.android.fortress.ingame.ExplostionAnimation.ExplosionCallback;
import com.hs.android.fortress.model.Bomb;
import com.hs.android.fortress.model.Player;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;

public class MainScreenFragment extends AbstractMainScreenFragment {

	private static final String TAG = "MainScreenFragment";


	public static final String INIT_POSITOIN = "init_position";

	private static final float MAX_ZOOM_LEVEL = 18f;
	private static final float MIN_ZOOM_LEVEL = 15f;
	private static final float MID_ZOOM_LEVEL = 17.8f;

	private static final int MODE_TILT70 = 0;
	private static final int MODE_TILT0 = 1;
	
	private static final double BAR_BELOW_VALUE = 0.0000850;

	private int currentMapMode;

	// private RelativeLayout mRelativeLayout;
	private MapView mMapView;
	private GoogleMap mMap;
	private Button mZoomInBtn;
	private Button mZoomOutBtn;
	private ImageButton mModeChangeBtn;

	private CameraPosition[] mModeCameraPosition;

	private boolean isFinish;

	private Marker imgExplosion;
	//private List<Marker> mEnemyTankMark;
	private Map<String, Marker> mProgressMarker;
	private CircleOptions circleOptions=null;
	private Circle circle=null;
	private Polyline line=null;
	private LatLng explosionLocation=null;
	private LatLng mLocation;
	private ImageView TankBomb;
	private SoundPool mPool;	
	private int mBombSound;


	private List<ProgressBar> mEnergyProgressbar;
	boolean energyProgressControl1=false;
	boolean energyProgressControl2=false;

	private String mUserId;
	private Player mPlayer;
	private Map<String, Player> mEnemyPlayers;
	private Map<String, Circle> mEnemyTankCircles;
	private Map<String, ProgressBar> mEnemyEnergyBar;
	private Circle mLocationCircle;
	
	private ExplostionAnimation mExAni;


	private int mRangeSound;
	private int mDamegedSound;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		mModeCameraPosition = new CameraPosition[2];
		
		mPlayer = ((GameApplication)getActivity().getApplication()).getPlayer();
		mUserId = mPlayer.getId();
		mLocation = mPlayer.getPosition();
		
		mEnemyTankCircles = new HashMap<String, Circle>();
		mProgressMarker = new HashMap<String, Marker>();
		mEnemyEnergyBar = new HashMap<String, ProgressBar>();
		mEnergyProgressbar = new ArrayList<ProgressBar>();
		mEnemyPlayers = new HashMap<String, Player>();
		
		isFinish = true;
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View v = inflater.inflate(R.layout.fragment_mainscreen, container,
				false);

		mMapView = (MapView) v.findViewById(R.id.mapview);
		mMapView.onCreate(savedInstanceState);
		

		TankBomb = (ImageView)v.findViewById(R.id.imgTankBomp);
		TankBomb.setImageResource(R.drawable.missail3);
		TankBomb.setVisibility(ImageView.INVISIBLE);
		int maxStreams = 10;
		mPool = new SoundPool(maxStreams, AudioManager.STREAM_MUSIC, 0);
		mBombSound = mPool.load(this.getActivity(), R.raw.bombfit, 0);
		mRangeSound = mPool.load(this.getActivity(), R.raw.range, 0);
		mDamegedSound = mPool.load(this.getActivity(), R.raw.targeted, 0);
		mEnergyProgressbar.add((ProgressBar)v.findViewById(R.id.enermyEnergyProgressBar1));
		mEnergyProgressbar.get(0).setVisibility(ProgressBar.INVISIBLE);
		mEnergyProgressbar.add((ProgressBar)v.findViewById(R.id.enermyEnergyProgressBar2));
		mEnergyProgressbar.get(1).setVisibility(ProgressBar.INVISIBLE);
		
		setUpMapMode();
		
		MapsInitializer.initialize(this.getActivity());
		mMap = mMapView.getMap();

		mExAni = new ExplostionAnimation(getActivity() , mMap);
		mExAni.setCallback(mExplosionCallback);
		
		currentMapMode = MODE_TILT70;
		setUpMap();
		
		setUpButton(v);
		
		return v;
	}

	@Override
	public void onResume() {
		super.onResume();
		mMapView.onResume();
	}
	@Override
	public void onDestroy() {
		super.onDestroy();
		mMapView.onDestroy();
	}

	@Override
	public void onLowMemory() {
		super.onLowMemory();
		mMapView.onLowMemory();
	}

	private void setUpMap() {

		UiSettings setting = mMap.getUiSettings();
		setting.setRotateGesturesEnabled(false);
		setting.setTiltGesturesEnabled(false);
		setting.setZoomControlsEnabled(false);
		setting.setZoomGesturesEnabled(false);
		setting.setCompassEnabled(false);
		setting.setScrollGesturesEnabled(false);
		setting.setMyLocationButtonEnabled(false);
		
		mMap.moveCamera(CameraUpdateFactory.newCameraPosition(mModeCameraPosition[currentMapMode]));
		
		drawMyLocation();
	}

	private boolean checkReady() {
		if (mMap == null) {
			return false;
		}
		return true;
	}

	private void setUpButton(View v) {
		mZoomInBtn = (Button) v.findViewById(R.id.btn_zoomin);
		mZoomInBtn.setOnClickListener(mClickListener);
		mZoomOutBtn = (Button) v.findViewById(R.id.btn_zoomout);
		mZoomOutBtn.setOnClickListener(mClickListener);
		mModeChangeBtn = (ImageButton) v.findViewById(R.id.btn_maprotate);
		mModeChangeBtn.setOnClickListener(mClickListener);
	}

	private OnClickListener mClickListener = new OnClickListener() {

		@Override
		public void onClick(View v) {
			switch (v.getId()) {
			case R.id.btn_zoomin:
				onZoomIn();
				break;

			case R.id.btn_zoomout:
				onZoomOut();
				break;

			case R.id.btn_maprotate:
				onChangeMapMode();
				break;
			}
		}
	};

	public void onZoomIn() {
		if (!checkReady()) {
			return;
		}
		if (mMap.getCameraPosition().zoom < MAX_ZOOM_LEVEL && isFinish){

			mMap.moveCamera(CameraUpdateFactory.zoomIn());
		}
	}

	public void onZoomOut() {
		if (!checkReady()) {
			return;
		}
		if (mMap.getCameraPosition().zoom > MIN_ZOOM_LEVEL && isFinish){

			mMap.moveCamera(CameraUpdateFactory.zoomOut());
		}
	}

	public void onChangeMapMode() {
		if (currentMapMode == MODE_TILT70) {
			currentMapMode = MODE_TILT0;
		} else if (currentMapMode == MODE_TILT0) {
			currentMapMode = MODE_TILT70;
		}

		if(isFinish){
			mMap.moveCamera(CameraUpdateFactory
					.newCameraPosition(mModeCameraPosition[currentMapMode]));
		}
	}

	public void screenRotate(float degree) {

		CameraPosition curPos = mMap.getCameraPosition();
		
		if(isFinish){
			mMap.moveCamera(CameraUpdateFactory
						.newCameraPosition(new CameraPosition(
								mLocation, curPos.zoom, curPos.tilt,
								degree)));

		}
	}
	
	protected void drawEnermyExplosion(LatLng pos, Bomb bomb){
		mExAni.startAnimation(pos, bomb, false);
	}
	
	public void drawExplosion(final LatLng pos, final Bomb bomb, float angle){
		explosionLocation = pos;
		
		TankBomb.setVisibility(ImageView.VISIBLE);
		if(imgExplosion!=null && line!=null && circle!=null){

			imgExplosion.remove();
			line.remove();
			circle.remove();
		}
		
		if(isFinish){
			isFinish = false;
			float zoom = 0;
			int uptime = 0;
			
			if(angle < 30){
				zoom = MAX_ZOOM_LEVEL;
				uptime = 700;
			}else if(30 <= angle && angle < 75){
				zoom = MID_ZOOM_LEVEL;
				uptime = 750;
			}else{
				zoom = MAX_ZOOM_LEVEL;
				uptime = 1500;
			}
			
			final int downtime = uptime/2;
			
			mMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition(mLocation, MAX_ZOOM_LEVEL, 90, mMap.getCameraPosition().bearing)));
			
			CameraPosition midCamPos = new CameraPosition(new LatLng((mLocation.latitude + explosionLocation.latitude)/2, (mLocation.longitude + explosionLocation.longitude)/2)
				, zoom, 90, mMap.getCameraPosition().bearing);
			
			
			final CameraPosition expCamPos = new CameraPosition(explosionLocation, mMap.getMaxZoomLevel(),
					0, mMap.getCameraPosition().bearing);
			
			mMap.animateCamera(CameraUpdateFactory.newCameraPosition(midCamPos), uptime, 
					new CancelableCallback() {
						
						@Override
						public void onFinish() {
							mMap.animateCamera(CameraUpdateFactory.newCameraPosition(expCamPos), downtime,
									new CancelableCallback() {
										
										@Override
										public void onFinish() {
											Log.d("Check", "isFinish?");
											TankBomb.setVisibility(ImageView.INVISIBLE);
											mPool.play(mBombSound,  1,  1, 0, 0, 1);
											mExAni.startAnimation(pos, bomb, true);
										}
										
										@Override
										public void onCancel() {
											Log.d("Check", "isCancel?");
										}
									});
						}
						
						@Override
						public void onCancel() {
							// TODO Auto-generated method stub
							
						}
					});
			
		}
	}


	private ExplosionCallback mExplosionCallback = new ExplosionCallback() {
		
		@Override
		public void callback() {
			try{
				getActivity().runOnUiThread(new Runnable() {
					@Override
					public void run() {
						imgExplosion = mMap.addMarker(new MarkerOptions()
						.position(explosionLocation)
						.icon(BitmapDescriptorFactory.fromResource(R.drawable.img_bomb)));
	
						circleOptions = new CircleOptions()
						.center(explosionLocation)
						.radius(10) 
						.strokeColor(0x80000000)
						.fillColor(0x8c000040);
	
						//TankBombed();
						circle = mMap.addCircle(circleOptions);
	
						line = mMap.addPolyline(new PolylineOptions()
						.add(mLocation, explosionLocation)
						.width(3)
						.color(Color.RED));
						
						CameraPosition beforCamPos = 
								new CameraPosition(mLocation, 18f, mModeCameraPosition[currentMapMode].tilt, mMap.getCameraPosition().bearing);
						
						mMap.moveCamera(CameraUpdateFactory.newCameraPosition(beforCamPos));
						isFinish = true;
					}
				});
			}catch(Exception e){
				
			}
		}
	};


//
	public void setPlayer(List<Player> players){

		for(Player p : players){
			if(p.getId().equals(mUserId))
				mPlayer = p;
			else
				mEnemyPlayers.put(p.getId(), p);
		}
	}
	
	@Override
	protected void setUpMapMode() {
		
		float zoom = MAX_ZOOM_LEVEL;
		float tilt = 50;
		float bearing = 0;

		mModeCameraPosition[MODE_TILT70] = new CameraPosition(mLocation, zoom,
				tilt, bearing);
		tilt = 0;
		mModeCameraPosition[MODE_TILT0] = new CameraPosition(mLocation, zoom,
				tilt, bearing);

	}
	
	public void drawMyLocation(){
		if(!checkReady())
			return;
		
		if(mLocationCircle == null){
			mLocationCircle = mMap.addCircle(makeDrawPlayerOpt(mLocation, Color.CYAN));
		}else{
			mLocationCircle.setCenter(mLocation);
		}
		
		
	}
	
	protected void drawEnermyLocation(){
		
		if(!checkReady())
			return;
		
		if(mEnemyTankCircles.isEmpty()){
			Iterator<Player> playerIterator = mEnemyPlayers.values().iterator();
			
			while(playerIterator.hasNext()){
				Player p = playerIterator.next();
				mEnemyTankCircles.put(p.getId(), mMap.addCircle(makeDrawPlayerOpt(p.getPosition(), Color.RED)));
			}
		}else{
			Iterator<Player> playerIterator = mEnemyPlayers.values().iterator();
			
			while(playerIterator.hasNext()){
				Player p = playerIterator.next();
				mEnemyTankCircles.get(p.getId()).setCenter(p.getPosition());
			}
		}
		
	}
	
	private CircleOptions makeDrawPlayerOpt(LatLng pos, int color){
		return new CircleOptions()
        .center(pos)
        .radius(5)
        .zIndex(5.0f)
        .strokeWidth(0.2f)
        .fillColor(color);
	}


	public void setEnermyProgress(){
		
		if(mEnemyEnergyBar.isEmpty() && mProgressMarker.isEmpty()){
			Iterator<Player> playerIterator = mEnemyPlayers.values().iterator();
			
			int index = 0;
			
			while(playerIterator.hasNext()){
				Player p = playerIterator.next();
				
				ProgressBar bar = mEnergyProgressbar.get(index++);
				bar.setMax(p.getTank().getMaxEnergy());
				
				bar.buildDrawingCache(true);
				Bitmap bm = bar.getDrawingCache(true);
				mEnemyEnergyBar.put(p.getId(), bar);
				
				mProgressMarker.put(p.getId(), mMap.addMarker(new MarkerOptions()
						.position(new LatLng(p.getLatitude()-BAR_BELOW_VALUE,p.getLongitude()))
						.icon(BitmapDescriptorFactory.fromBitmap(bm))
						.title(p.getId())
						));
			}
		}else{
			Iterator<Player> playerIterator = mEnemyPlayers.values().iterator();
			
			while(playerIterator.hasNext()){
				Player p = playerIterator.next();
				
				ProgressBar bar = mEnemyEnergyBar.get(p.getId());
				int energy = p.getEnergy();
				if(energy < 0 )
					energy = 0;
				bar.setProgress(energy);
				bar.buildDrawingCache(true);
				Bitmap bm = bar.getDrawingCache(true);
				
				Marker pm = mProgressMarker.get(p.getId());
				pm.setPosition(new LatLng(p.getLatitude()-BAR_BELOW_VALUE,p.getLongitude()));
				pm.setIcon(BitmapDescriptorFactory.fromBitmap(bm));
			}
		}
	}
	
	public boolean isFinish(){
		return isFinish;
	}
	
}
